home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python152_Src.lha / Python152_Source / Objects / fileobject.c < prev    next >
C/C++ Source or Header  |  1999-04-25  |  23KB  |  1,108 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI or Corporation for National Research Initiatives or
  13. CNRI not be used in advertising or publicity pertaining to
  14. distribution of the software without specific, written prior
  15. permission.
  16.  
  17. While CWI is the initial source for this software, a modified version
  18. is made available by the Corporation for National Research Initiatives
  19. (CNRI) at the Internet address ftp://ftp.python.org.
  20.  
  21. STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
  22. REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  23. MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
  24. CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  25. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  27. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  28. PERFORMANCE OF THIS SOFTWARE.
  29.  
  30. ******************************************************************/
  31.  
  32. /* File object implementation */
  33.  
  34. #include "Python.h"
  35. #include "structmember.h"
  36.  
  37. #include <sys/types.h>
  38.  
  39. #ifdef HAVE_UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42.  
  43. #ifdef MS_WIN32
  44. #define ftruncate _chsize
  45. #define fileno _fileno
  46. #define HAVE_FTRUNCATE
  47. #endif
  48.  
  49. #ifdef macintosh
  50. #ifdef USE_GUSI
  51. #define HAVE_FTRUNCATE
  52. #endif
  53. #endif
  54.  
  55. #ifdef THINK_C
  56. #define HAVE_FOPENRF
  57. #endif
  58. #ifdef __MWERKS__
  59. /* Mwerks fopen() doesn't always set errno */
  60. #define NO_FOPEN_ERRNO
  61. #endif
  62.  
  63. #define BUF(v) PyString_AS_STRING((PyStringObject *)v)
  64.  
  65. #include <errno.h>
  66.  
  67. typedef struct {
  68.     PyObject_HEAD
  69.     FILE *f_fp;
  70.     PyObject *f_name;
  71.     PyObject *f_mode;
  72.     int (*f_close) Py_PROTO((FILE *));
  73.     int f_softspace; /* Flag used by 'print' command */
  74. } PyFileObject;
  75.  
  76. #include "protos/fileobject.h"
  77.  
  78. FILE *
  79. PyFile_AsFile(f)
  80.     PyObject *f;
  81. {
  82.     if (f == NULL || !PyFile_Check(f))
  83.         return NULL;
  84.     else
  85.         return ((PyFileObject *)f)->f_fp;
  86. }
  87.  
  88. PyObject *
  89. PyFile_Name(f)
  90.     PyObject *f;
  91. {
  92.     if (f == NULL || !PyFile_Check(f))
  93.         return NULL;
  94.     else
  95.         return ((PyFileObject *)f)->f_name;
  96. }
  97.  
  98. PyObject *
  99. PyFile_FromFile(fp, name, mode, close)
  100.     FILE *fp;
  101.     char *name;
  102.     char *mode;
  103.     int (*close) Py_FPROTO((FILE *));
  104. {
  105.     PyFileObject *f = PyObject_NEW(PyFileObject, &PyFile_Type);
  106.     if (f == NULL)
  107.         return NULL;
  108.     f->f_fp = NULL;
  109.     f->f_name = PyString_FromString(name);
  110.     f->f_mode = PyString_FromString(mode);
  111.     f->f_close = close;
  112.     f->f_softspace = 0;
  113.     if (f->f_name == NULL || f->f_mode == NULL) {
  114.         Py_DECREF(f);
  115.         return NULL;
  116.     }
  117.     f->f_fp = fp;
  118.     return (PyObject *) f;
  119. }
  120.  
  121. PyObject *
  122. PyFile_FromString(name, mode)
  123.     char *name, *mode;
  124. {
  125.     extern int fclose Py_PROTO((FILE *));
  126.     PyFileObject *f;
  127.     f = (PyFileObject *) PyFile_FromFile((FILE *)NULL, name, mode, fclose);
  128.     if (f == NULL)
  129.         return NULL;
  130. #ifdef HAVE_FOPENRF
  131.     if (*mode == '*') {
  132.         FILE *fopenRF();
  133.         f->f_fp = fopenRF(name, mode+1);
  134.     }
  135.     else
  136. #endif
  137.     {
  138.         Py_BEGIN_ALLOW_THREADS
  139.         f->f_fp = fopen(name, mode);
  140.         Py_END_ALLOW_THREADS
  141.     }
  142.     if (f->f_fp == NULL) {
  143. #ifdef NO_FOPEN_ERRNO
  144.         /* Metroworks only, not testable, so unchanged */
  145.         if ( errno == 0 ) {
  146.             PyErr_SetString(PyExc_IOError, "Cannot open file");
  147.             Py_DECREF(f);
  148.             return NULL;
  149.         }
  150. #endif
  151.         PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
  152.         Py_DECREF(f);
  153.         return NULL;
  154.     }
  155.     return (PyObject *)f;
  156. }
  157.  
  158. void
  159. PyFile_SetBufSize(f, bufsize)
  160.     PyObject *f;
  161.     int bufsize;
  162. {
  163.     if (bufsize >= 0) {
  164. #ifdef HAVE_SETVBUF
  165.         int type;
  166.         switch (bufsize) {
  167.         case 0:
  168.             type = _IONBF;
  169.             break;
  170.         case 1:
  171.             type = _IOLBF;
  172.             bufsize = BUFSIZ;
  173.             break;
  174.         default:
  175.             type = _IOFBF;
  176.         }
  177.         setvbuf(((PyFileObject *)f)->f_fp, (char *)NULL,
  178.             type, bufsize);
  179. #else /* !HAVE_SETVBUF */
  180.         if (bufsize <= 1)
  181.             setbuf(((PyFileObject *)f)->f_fp, (char *)NULL);
  182. #endif /* !HAVE_SETVBUF */
  183.     }
  184. }
  185.  
  186. static PyObject *
  187. err_closed()
  188. {
  189.     PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
  190.     return NULL;
  191. }
  192.  
  193. /* Methods */
  194.  
  195. static void
  196. file_dealloc(f)
  197.     PyFileObject *f;
  198. {
  199.     if (f->f_fp != NULL && f->f_close != NULL) {
  200.         Py_BEGIN_ALLOW_THREADS
  201.         (*f->f_close)(f->f_fp);
  202.         Py_END_ALLOW_THREADS
  203.     }
  204.     if (f->f_name != NULL) {
  205.         Py_DECREF(f->f_name);
  206.     }
  207.     if (f->f_mode != NULL) {
  208.         Py_DECREF(f->f_mode);
  209.     }
  210.     free((char *)f);
  211. }
  212.  
  213. static PyObject *
  214. file_repr(f)
  215.     PyFileObject *f;
  216. {
  217.     char buf[300];
  218.     sprintf(buf, "<%s file '%.256s', mode '%.10s' at %lx>",
  219.         f->f_fp == NULL ? "closed" : "open",
  220.         PyString_AsString(f->f_name),
  221.         PyString_AsString(f->f_mode),
  222.         (long)f);
  223.     return PyString_FromString(buf);
  224. }
  225.  
  226. static PyObject *
  227. file_close(f, args)
  228.     PyFileObject *f;
  229.     PyObject *args;
  230. {
  231.     int sts = 0;
  232.     if (!PyArg_NoArgs(args))
  233.         return NULL;
  234.     if (f->f_fp != NULL) {
  235.         if (f->f_close != NULL) {
  236.             Py_BEGIN_ALLOW_THREADS
  237.             errno = 0;
  238.             sts = (*f->f_close)(f->f_fp);
  239.             Py_END_ALLOW_THREADS
  240.         }
  241.         f->f_fp = NULL;
  242.     }
  243.     if (sts == EOF)
  244.         return PyErr_SetFromErrno(PyExc_IOError);
  245.     if (sts != 0)
  246.         return PyInt_FromLong((long)sts);
  247.     Py_INCREF(Py_None);
  248.     return Py_None;
  249. }
  250.  
  251. static PyObject *
  252. file_seek(f, args)
  253.     PyFileObject *f;
  254.     PyObject *args;
  255. {
  256.     int whence;
  257.     int ret;
  258.     off_t offset;
  259.     PyObject *offobj;
  260.     
  261.     if (f->f_fp == NULL)
  262.         return err_closed();
  263.     whence = 0;
  264.     if (!PyArg_ParseTuple(args, "O|i", &offobj, &whence))
  265.         return NULL;
  266. #if !defined(HAVE_LARGEFILE_SUPPORT)
  267.     offset = PyInt_AsLong(offobj);
  268. #else
  269.     offset = PyLong_Check(offobj) ?
  270.         PyLong_AsLongLong(offobj) : PyInt_AsLong(offobj);
  271. #endif
  272.     if (PyErr_Occurred())
  273.         return NULL;
  274.     Py_BEGIN_ALLOW_THREADS
  275.     errno = 0;
  276. #if defined(HAVE_FSEEKO)
  277.     ret = fseeko(f->f_fp, offset, whence);
  278. #elif defined(HAVE_FSEEK64)
  279.     ret = fseek64(f->f_fp, offset, whence);
  280. #else
  281.     ret = fseek(f->f_fp, offset, whence);
  282. #endif
  283.     Py_END_ALLOW_THREADS
  284.     if (ret != 0) {
  285.         PyErr_SetFromErrno(PyExc_IOError);
  286.         clearerr(f->f_fp);
  287.         return NULL;
  288.     }
  289.     Py_INCREF(Py_None);
  290.     return Py_None;
  291. }
  292.  
  293. #ifdef HAVE_FTRUNCATE
  294. static PyObject *
  295. file_truncate(f, args)
  296.     PyFileObject *f;
  297.     PyObject *args;
  298. {
  299.     int ret;
  300.     off_t newsize;
  301.     PyObject *newsizeobj;
  302.     
  303.     if (f->f_fp == NULL)
  304.         return err_closed();
  305.     newsizeobj = NULL;
  306.     if (!PyArg_ParseTuple(args, "|O", &newsizeobj))
  307.         return NULL;
  308.     if (newsizeobj != NULL) {
  309. #if !defined(HAVE_LARGEFILE_SUPPORT)
  310.         newsize = PyInt_AsLong(newsizeobj);
  311. #else
  312.         newsize = PyLong_Check(newsizeobj) ?
  313.                 PyLong_AsLongLong(newsizeobj) :
  314.                 PyInt_AsLong(newsizeobj);
  315. #endif
  316.         if (PyErr_Occurred())
  317.             return NULL;
  318.     } else {
  319.         /* Default to current position*/
  320.         Py_BEGIN_ALLOW_THREADS
  321.         errno = 0;
  322. #if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
  323.         newsize =  ftello(f->f_fp);
  324. #elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
  325.         newsize =  ftell64(f->f_fp);
  326. #else
  327.         newsize =  ftell(f->f_fp);
  328. #endif
  329.         Py_END_ALLOW_THREADS
  330.         if (newsize == -1) {
  331.                 PyErr_SetFromErrno(PyExc_IOError);
  332.             clearerr(f->f_fp);
  333.             return NULL;
  334.         }
  335.     }
  336.     Py_BEGIN_ALLOW_THREADS
  337.     errno = 0;
  338.     ret = fflush(f->f_fp);
  339.     Py_END_ALLOW_THREADS
  340.     if (ret == 0) {
  341.             Py_BEGIN_ALLOW_THREADS
  342.         errno = 0;
  343.         ret = ftruncate(fileno(f->f_fp), newsize);
  344.         Py_END_ALLOW_THREADS
  345.     }
  346.     if (ret != 0) {
  347.         PyErr_SetFromErrno(PyExc_IOError);
  348.         clearerr(f->f_fp);
  349.         return NULL;
  350.     }
  351.     Py_INCREF(Py_None);
  352.     return Py_None;
  353. }
  354. #endif /* HAVE_FTRUNCATE */
  355.  
  356. static PyObject *
  357. file_tell(f, args)
  358.     PyFileObject *f;
  359.     PyObject *args;
  360. {
  361.     off_t offset;
  362.     if (f->f_fp == NULL)
  363.         return err_closed();
  364.     if (!PyArg_NoArgs(args))
  365.         return NULL;
  366.     Py_BEGIN_ALLOW_THREADS
  367.     errno = 0;
  368. #if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
  369.     offset = ftello(f->f_fp);
  370. #elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
  371.     offset = ftell64(f->f_fp);
  372. #else
  373.     offset = ftell(f->f_fp);
  374. #endif
  375.     Py_END_ALLOW_THREADS
  376.     if (offset == -1) {
  377.         PyErr_SetFromErrno(PyExc_IOError);
  378.         clearerr(f->f_fp);
  379.         return NULL;
  380.     }
  381. #if !defined(HAVE_LARGEFILE_SUPPORT)
  382.     return PyInt_FromLong(offset);
  383. #else
  384.     return PyLong_FromLongLong(offset);
  385. #endif
  386. }
  387.  
  388. static PyObject *
  389. file_fileno(f, args)
  390.     PyFileObject *f;
  391.     PyObject *args;
  392. {
  393.     if (f->f_fp == NULL)
  394.         return err_closed();
  395.     if (!PyArg_NoArgs(args))
  396.         return NULL;
  397.     return PyInt_FromLong((long) fileno(f->f_fp));
  398. }
  399.  
  400. static PyObject *
  401. file_flush(f, args)
  402.     PyFileObject *f;
  403.     PyObject *args;
  404. {
  405.     int res;
  406.     
  407.     if (f->f_fp == NULL)
  408.         return err_closed();
  409.     if (!PyArg_NoArgs(args))
  410.         return NULL;
  411.     Py_BEGIN_ALLOW_THREADS
  412.     errno = 0;
  413.     res = fflush(f->f_fp);
  414.     Py_END_ALLOW_THREADS
  415.     if (res != 0) {
  416.         PyErr_SetFromErrno(PyExc_IOError);
  417.         clearerr(f->f_fp);
  418.         return NULL;
  419.     }
  420.     Py_INCREF(Py_None);
  421.     return Py_None;
  422. }
  423.  
  424. static PyObject *
  425. file_isatty(f, args)
  426.     PyFileObject *f;
  427.     PyObject *args;
  428. {
  429.     long res;
  430.     if (f->f_fp == NULL)
  431.         return err_closed();
  432.     if (!PyArg_NoArgs(args))
  433.         return NULL;
  434.     Py_BEGIN_ALLOW_THREADS
  435.     res = isatty((int)fileno(f->f_fp));
  436.     Py_END_ALLOW_THREADS
  437.     return PyInt_FromLong(res);
  438. }
  439.  
  440. /* We expect that fstat exists on most systems.
  441.    It's confirmed on Unix, Mac and Windows.
  442.    If you don't have it, add #define DONT_HAVE_FSTAT to your config.h. */
  443. #ifndef DONT_HAVE_FSTAT
  444. #define HAVE_FSTAT
  445.  
  446. #include <sys/types.h>
  447. #include <sys/stat.h>
  448.  
  449. #endif
  450.  
  451. #if BUFSIZ < 8192
  452. #define SMALLCHUNK 8192
  453. #else
  454. #define SMALLCHUNK BUFSIZ
  455. #endif
  456.  
  457. #if SIZEOF_INT < 4
  458. #define BIGCHUNK  (512 * 32)
  459. #else
  460. #define BIGCHUNK  (512 * 1024)
  461. #endif
  462.  
  463. static size_t
  464. new_buffersize(f, currentsize)
  465.     PyFileObject *f;
  466.     size_t currentsize;
  467. {
  468. #ifdef HAVE_FSTAT
  469.     long pos, end;
  470.     struct stat st;
  471.     if (fstat(fileno(f->f_fp), &st) == 0) {
  472.         end = st.st_size;
  473.         /* The following is not a bug: we really need to call lseek()
  474.            *and* ftell().  The reason is that some stdio libraries
  475.            mistakenly flush their buffer when ftell() is called and
  476.            the lseek() call it makes fails, thereby throwing away
  477.            data that cannot be recovered in any way.  To avoid this,
  478.            we first test lseek(), and only call ftell() if lseek()
  479.            works.  We can't use the lseek() value either, because we
  480.            need to take the amount of buffered data into account.
  481.            (Yet another reason why stdio stinks. :-) */
  482.         pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
  483.         if (pos >= 0)
  484.             pos = ftell(f->f_fp);
  485.         if (pos < 0)
  486.             clearerr(f->f_fp);
  487.         if (end > pos && pos >= 0)
  488.             return currentsize + end - pos + 1;
  489.         /* Add 1 so if the file were to grow we'd notice. */
  490.     }
  491. #endif
  492.     if (currentsize > SMALLCHUNK) {
  493.         /* Keep doubling until we reach BIGCHUNK;
  494.            then keep adding BIGCHUNK. */
  495.         if (currentsize <= BIGCHUNK)
  496.             return currentsize + currentsize;
  497.         else
  498.             return currentsize + BIGCHUNK;
  499.     }
  500.     return currentsize + SMALLCHUNK;
  501. }
  502.  
  503. static PyObject *
  504. file_read(f, args)
  505.     PyFileObject *f;
  506.     PyObject *args;
  507. {
  508.     long bytesrequested = -1;
  509.     size_t bytesread, buffersize, chunksize;
  510.     PyObject *v;
  511.     
  512.     if (f->f_fp == NULL)
  513.         return err_closed();
  514.     if (!PyArg_ParseTuple(args, "|l", &bytesrequested))
  515.         return NULL;
  516.     if (bytesrequested < 0)
  517.         buffersize = new_buffersize(f, (size_t)0);
  518.     else
  519.         buffersize = bytesrequested;
  520.     v = PyString_FromStringAndSize((char *)NULL, buffersize);
  521.     if (v == NULL)
  522.         return NULL;
  523.     bytesread = 0;
  524.     for (;;) {
  525.         Py_BEGIN_ALLOW_THREADS
  526.         errno = 0;
  527.         chunksize = fread(BUF(v) + bytesread, 1,
  528.                   buffersize - bytesread, f->f_fp);
  529.         Py_END_ALLOW_THREADS
  530.         if (chunksize == 0) {
  531.             if (!ferror(f->f_fp))
  532.                 break;
  533.             PyErr_SetFromErrno(PyExc_IOError);
  534.             clearerr(f->f_fp);
  535.             Py_DECREF(v);
  536.             return NULL;
  537.         }
  538.         bytesread += chunksize;
  539.         if (bytesread < buffersize)
  540.             break;
  541.         if (bytesrequested < 0) {
  542.             buffersize = new_buffersize(f, buffersize);
  543.             if (_PyString_Resize(&v, buffersize) < 0)
  544.                 return NULL;
  545.         }
  546.     }
  547.     if (bytesread != buffersize)
  548.         _PyString_Resize(&v, bytesread);
  549.     return v;
  550. }
  551.  
  552. static PyObject *
  553. file_readinto(f, args)
  554.     PyFileObject *f;
  555.     PyObject *args;
  556. {
  557.     char *ptr;
  558.     int ntodo, ndone, nnow;
  559.     
  560.     if (f->f_fp == NULL)
  561.         return err_closed();
  562.     if (!PyArg_Parse(args, "w#", &ptr, &ntodo))
  563.         return NULL;
  564.     ndone = 0;
  565.     while (ntodo > 0) {
  566.         Py_BEGIN_ALLOW_THREADS
  567.         errno = 0;
  568.         nnow = fread(ptr+ndone, 1, ntodo, f->f_fp);
  569.         Py_END_ALLOW_THREADS
  570.         if (nnow == 0) {
  571.             if (!ferror(f->f_fp))
  572.                 break;
  573.             PyErr_SetFromErrno(PyExc_IOError);
  574.             clearerr(f->f_fp);
  575.             return NULL;
  576.         }
  577.         ndone += nnow;
  578.         ntodo -= nnow;
  579.     }
  580.     return PyInt_FromLong(ndone);
  581. }
  582.  
  583.  
  584. /* Internal routine to get a line.
  585.    Size argument interpretation:
  586.    > 0: max length;
  587.    = 0: read arbitrary line;
  588.    < 0: strip trailing '\n', raise EOFError if EOF reached immediately
  589. */
  590.  
  591. static PyObject *
  592. getline(f, n)
  593.     PyFileObject *f;
  594.     int n;
  595. {
  596.     register FILE *fp;
  597.     register int c;
  598.     register char *buf, *end;
  599.     int n1, n2;
  600.     PyObject *v;
  601.  
  602.     fp = f->f_fp;
  603.     n2 = n > 0 ? n : 100;
  604.     v = PyString_FromStringAndSize((char *)NULL, n2);
  605.     if (v == NULL)
  606.         return NULL;
  607.     buf = BUF(v);
  608.     end = buf + n2;
  609.  
  610.     Py_BEGIN_ALLOW_THREADS
  611.     for (;;) {
  612.         if ((c = getc(fp)) == EOF) {
  613.             clearerr(fp);
  614.             Py_BLOCK_THREADS
  615.             if (PyErr_CheckSignals()) {
  616.                 Py_DECREF(v);
  617.                 return NULL;
  618.             }
  619.             if (n < 0 && buf == BUF(v)) {
  620.                 Py_DECREF(v);
  621.                 PyErr_SetString(PyExc_EOFError,
  622.                        "EOF when reading a line");
  623.                 return NULL;
  624.             }
  625.             Py_UNBLOCK_THREADS
  626.             break;
  627.         }
  628.         if ((*buf++ = c) == '\n') {
  629.             if (n < 0)
  630.                 buf--;
  631.             break;
  632.         }
  633.         if (buf == end) {
  634.             if (n > 0)
  635.                 break;
  636.             n1 = n2;
  637.             n2 += 1000;
  638.             Py_BLOCK_THREADS
  639.             if (_PyString_Resize(&v, n2) < 0)
  640.                 return NULL;
  641.             Py_UNBLOCK_THREADS
  642.             buf = BUF(v) + n1;
  643.             end = BUF(v) + n2;
  644.         }
  645.     }
  646.     Py_END_ALLOW_THREADS
  647.  
  648.     n1 = buf - BUF(v);
  649.     if (n1 != n2)
  650.         _PyString_Resize(&v, n1);
  651.     return v;
  652. }
  653.  
  654. /* External C interface */
  655.  
  656. PyObject *
  657. PyFile_GetLine(f, n)
  658.     PyObject *f;
  659.     int n;
  660. {
  661.     if (f == NULL) {
  662.         PyErr_BadInternalCall();
  663.         return NULL;
  664.     }
  665.     if (!PyFile_Check(f)) {
  666.         PyObject *reader;
  667.         PyObject *args;
  668.         PyObject *result;
  669.         reader = PyObject_GetAttrString(f, "readline");
  670.         if (reader == NULL)
  671.             return NULL;
  672.         if (n <= 0)
  673.             args = Py_BuildValue("()");
  674.         else
  675.             args = Py_BuildValue("(i)", n);
  676.         if (args == NULL) {
  677.             Py_DECREF(reader);
  678.             return NULL;
  679.         }
  680.         result = PyEval_CallObject(reader, args);
  681.         Py_DECREF(reader);
  682.         Py_DECREF(args);
  683.         if (result != NULL && !PyString_Check(result)) {
  684.             Py_DECREF(result);
  685.             result = NULL;
  686.             PyErr_SetString(PyExc_TypeError,
  687.                    "object.readline() returned non-string");
  688.         }
  689.         if (n < 0 && result != NULL) {
  690.             char *s = PyString_AsString(result);
  691.             int len = PyString_Size(result);
  692.             if (len == 0) {
  693.                 Py_DECREF(result);
  694.                 result = NULL;
  695.                 PyErr_SetString(PyExc_EOFError,
  696.                        "EOF when reading a line");
  697.             }
  698.             else if (s[len-1] == '\n') {
  699.                 if (result->ob_refcnt == 1)
  700.                     _PyString_Resize(&result, len-1);
  701.                 else {
  702.                     PyObject *v;
  703.                     v = PyString_FromStringAndSize(s,
  704.                                        len-1);
  705.                     Py_DECREF(result);
  706.                     result = v;
  707.                 }
  708.             }
  709.         }
  710.         return result;
  711.     }
  712.     if (((PyFileObject*)f)->f_fp == NULL)
  713.         return err_closed();
  714.     return getline((PyFileObject *)f, n);
  715. }
  716.  
  717. /* Python method */
  718.  
  719. static PyObject *
  720. file_readline(f, args)
  721.     PyFileObject *f;
  722.     PyObject *args;
  723. {
  724.     int n = -1;
  725.  
  726.     if (f->f_fp == NULL)
  727.         return err_closed();
  728.     if (!PyArg_ParseTuple(args, "|i", &n))
  729.         return NULL;
  730.     if (n == 0)
  731.         return PyString_FromString("");
  732.     if (n < 0)
  733.         n = 0;
  734.     return getline(f, n);
  735. }
  736.  
  737. static PyObject *
  738. file_readlines(f, args)
  739.     PyFileObject *f;
  740.     PyObject *args;
  741. {
  742.     long sizehint = 0;
  743.     PyObject *list;
  744.     PyObject *line;
  745.     char small_buffer[SMALLCHUNK];
  746.     char *buffer = small_buffer;
  747.     size_t buffersize = SMALLCHUNK;
  748.     PyObject *big_buffer = NULL;
  749.     size_t nfilled = 0;
  750.     size_t nread;
  751.     size_t totalread = 0;
  752.     char *p, *q, *end;
  753.     int err;
  754.  
  755.     if (f->f_fp == NULL)
  756.         return err_closed();
  757.     if (!PyArg_ParseTuple(args, "|l", &sizehint))
  758.         return NULL;
  759.     if ((list = PyList_New(0)) == NULL)
  760.         return NULL;
  761.     for (;;) {
  762.         Py_BEGIN_ALLOW_THREADS
  763.         errno = 0;
  764.         nread = fread(buffer+nfilled, 1, buffersize-nfilled, f->f_fp);
  765.         Py_END_ALLOW_THREADS
  766.         if (nread == 0) {
  767.             sizehint = 0;
  768.             if (!ferror(f->f_fp))
  769.                 break;
  770.             PyErr_SetFromErrno(PyExc_IOError);
  771.             clearerr(f->f_fp);
  772.           error:
  773.             Py_DECREF(list);
  774.             list = NULL;
  775.             goto cleanup;
  776.         }
  777.         totalread += nread;
  778.         p = memchr(buffer+nfilled, '\n', nread);
  779.         if (p == NULL) {
  780.             /* Need a larger buffer to fit this line */
  781.             nfilled += nread;
  782.             buffersize *= 2;
  783.             if (big_buffer == NULL) {
  784.                 /* Create the big buffer */
  785.                 big_buffer = PyString_FromStringAndSize(
  786.                     NULL, buffersize);
  787.                 if (big_buffer == NULL)
  788.                     goto error;
  789.                 buffer = PyString_AS_STRING(big_buffer);
  790.                 memcpy(buffer, small_buffer, nfilled);
  791.             }
  792.             else {
  793.                 /* Grow the big buffer */
  794.                 _PyString_Resize(&big_buffer, buffersize);
  795.                 buffer = PyString_AS_STRING(big_buffer);
  796.             }
  797.             continue;
  798.         }
  799.         end = buffer+nfilled+nread;
  800.         q = buffer;
  801.         do {
  802.             /* Process complete lines */
  803.             p++;
  804.             line = PyString_FromStringAndSize(q, p-q);
  805.             if (line == NULL)
  806.                 goto error;
  807.             err = PyList_Append(list, line);
  808.             Py_DECREF(line);
  809.             if (err != 0)
  810.                 goto error;
  811.             q = p;
  812.             p = memchr(q, '\n', end-q);
  813.         } while (p != NULL);
  814.         /* Move the remaining incomplete line to the start */
  815.         nfilled = end-q;
  816.         memmove(buffer, q, nfilled);
  817.         if (sizehint > 0)
  818.             if (totalread >= (size_t)sizehint)
  819.                 break;
  820.     }
  821.     if (nfilled != 0) {
  822.         /* Partial last line */
  823.         line = PyString_FromStringAndSize(buffer, nfilled);
  824.         if (line == NULL)
  825.             goto error;
  826.         if (sizehint > 0) {
  827.             /* Need to complete the last line */
  828.             PyObject *rest = getline(f, 0);
  829.             if (rest == NULL) {
  830.                 Py_DECREF(line);
  831.                 goto error;
  832.             }
  833.             PyString_Concat(&line, rest);
  834.             Py_DECREF(rest);
  835.             if (line == NULL)
  836.                 goto error;
  837.         }
  838.         err = PyList_Append(list, line);
  839.         Py_DECREF(line);
  840.         if (err != 0)
  841.             goto error;
  842.     }
  843.   cleanup:
  844.     if (big_buffer) {
  845.         Py_DECREF(big_buffer);
  846.     }
  847.     return list;
  848. }
  849.  
  850. static PyObject *
  851. file_write(f, args)
  852.     PyFileObject *f;
  853.     PyObject *args;
  854. {
  855.     char *s;
  856.     int n, n2;
  857.     if (f->f_fp == NULL)
  858.         return err_closed();
  859.     if (!PyArg_Parse(args, "s#", &s, &n))
  860.         return NULL;
  861.     f->f_softspace = 0;
  862.     Py_BEGIN_ALLOW_THREADS
  863.     errno = 0;
  864.     n2 = fwrite(s, 1, n, f->f_fp);
  865.     Py_END_ALLOW_THREADS
  866.     if (n2 != n) {
  867.         PyErr_SetFromErrno(PyExc_IOError);
  868.         clearerr(f->f_fp);
  869.         return NULL;
  870.     }
  871.     Py_INCREF(Py_None);
  872.     return Py_None;
  873. }
  874.  
  875. static PyObject *
  876. file_writelines(f, args)
  877.     PyFileObject *f;
  878.     PyObject *args;
  879. {
  880.     int i, n;
  881.     if (f->f_fp == NULL)
  882.         return err_closed();
  883.     if (args == NULL || !PyList_Check(args)) {
  884.         PyErr_SetString(PyExc_TypeError,
  885.                "writelines() requires list of strings");
  886.         return NULL;
  887.     }
  888.     n = PyList_Size(args);
  889.     f->f_softspace = 0;
  890.     Py_BEGIN_ALLOW_THREADS
  891.     errno = 0;
  892.     for (i = 0; i < n; i++) {
  893.         PyObject *line = PyList_GetItem(args, i);
  894.         int len;
  895.         int nwritten;
  896.         if (!PyString_Check(line)) {
  897.             Py_BLOCK_THREADS
  898.             PyErr_SetString(PyExc_TypeError,
  899.                    "writelines() requires list of strings");
  900.             return NULL;
  901.         }
  902.         len = PyString_Size(line);
  903.         nwritten = fwrite(PyString_AsString(line), 1, len, f->f_fp);
  904.         if (nwritten != len) {
  905.             Py_BLOCK_THREADS
  906.             PyErr_SetFromErrno(PyExc_IOError);
  907.             clearerr(f->f_fp);
  908.             return NULL;
  909.         }
  910.     }
  911.     Py_END_ALLOW_THREADS
  912.     Py_INCREF(Py_None);
  913.     return Py_None;
  914. }
  915.  
  916. static PyMethodDef file_methods[] = {
  917.     {"readline",    (PyCFunction)file_readline, 1},
  918.     {"read",    (PyCFunction)file_read, 1},
  919.     {"write",    (PyCFunction)file_write, 0},
  920.     {"fileno",    (PyCFunction)file_fileno, 0},
  921.     {"seek",    (PyCFunction)file_seek, 1},
  922. #ifdef HAVE_FTRUNCATE
  923.     {"truncate",    (PyCFunction)file_truncate, 1},
  924. #endif
  925.     {"tell",    (PyCFunction)file_tell, 0},
  926.     {"readinto",    (PyCFunction)file_readinto, 0},
  927.     {"readlines",    (PyCFunction)file_readlines, 1},
  928.     {"writelines",    (PyCFunction)file_writelines, 0},
  929.     {"flush",    (PyCFunction)file_flush, 0},
  930.     {"close",    (PyCFunction)file_close, 0},
  931.     {"isatty",    (PyCFunction)file_isatty, 0},
  932.     {NULL,        NULL}        /* sentinel */
  933. };
  934.  
  935. #define OFF(x) offsetof(PyFileObject, x)
  936.  
  937. static struct memberlist file_memberlist[] = {
  938.     {"softspace",    T_INT,        OFF(f_softspace)},
  939.     {"mode",    T_OBJECT,    OFF(f_mode),    RO},
  940.     {"name",    T_OBJECT,    OFF(f_name),    RO},
  941.     /* getattr(f, "closed") is implemented without this table */
  942.     {"closed",    T_INT,        0,        RO},
  943.     {NULL}    /* Sentinel */
  944. };
  945.  
  946. static PyObject *
  947. file_getattr(f, name)
  948.     PyFileObject *f;
  949.     char *name;
  950. {
  951.     PyObject *res;
  952.  
  953.     res = Py_FindMethod(file_methods, (PyObject *)f, name);
  954.     if (res != NULL)
  955.         return res;
  956.     PyErr_Clear();
  957.     if (strcmp(name, "closed") == 0)
  958.         return PyInt_FromLong((long)(f->f_fp == 0));
  959.     return PyMember_Get((char *)f, file_memberlist, name);
  960. }
  961.  
  962. static int
  963. file_setattr(f, name, v)
  964.     PyFileObject *f;
  965.     char *name;
  966.     PyObject *v;
  967. {
  968.     if (v == NULL) {
  969.         PyErr_SetString(PyExc_AttributeError,
  970.                 "can't delete file attributes");
  971.         return -1;
  972.     }
  973.     return PyMember_Set((char *)f, file_memberlist, name, v);
  974. }
  975.  
  976. PyTypeObject PyFile_Type = {
  977.     PyObject_HEAD_INIT(&PyType_Type)
  978.     0,
  979.     "file",
  980.     sizeof(PyFileObject),
  981.     0,
  982.     (destructor)file_dealloc, /*tp_dealloc*/
  983.     0,        /*tp_print*/
  984.     (getattrfunc)file_getattr, /*tp_getattr*/
  985.     (setattrfunc)file_setattr, /*tp_setattr*/
  986.     0,        /*tp_compare*/
  987.     (reprfunc)file_repr, /*tp_repr*/
  988. };
  989.  
  990. /* Interface for the 'soft space' between print items. */
  991.  
  992. int
  993. PyFile_SoftSpace(f, newflag)
  994.     PyObject *f;
  995.     int newflag;
  996. {
  997.     int oldflag = 0;
  998.     if (f == NULL) {
  999.         /* Do nothing */
  1000.     }
  1001.     else if (PyFile_Check(f)) {
  1002.         oldflag = ((PyFileObject *)f)->f_softspace;
  1003.         ((PyFileObject *)f)->f_softspace = newflag;
  1004.     }
  1005.     else {
  1006.         PyObject *v;
  1007.         v = PyObject_GetAttrString(f, "softspace");
  1008.         if (v == NULL)
  1009.             PyErr_Clear();
  1010.         else {
  1011.             if (PyInt_Check(v))
  1012.                 oldflag = PyInt_AsLong(v);
  1013.             Py_DECREF(v);
  1014.         }
  1015.         v = PyInt_FromLong((long)newflag);
  1016.         if (v == NULL)
  1017.             PyErr_Clear();
  1018.         else {
  1019.             if (PyObject_SetAttrString(f, "softspace", v) != 0)
  1020.                 PyErr_Clear();
  1021.             Py_DECREF(v);
  1022.         }
  1023.     }
  1024.     return oldflag;
  1025. }
  1026.  
  1027. /* Interfaces to write objects/strings to file-like objects */
  1028.  
  1029. int
  1030. PyFile_WriteObject(v, f, flags)
  1031.     PyObject *v;
  1032.     PyObject *f;
  1033.     int flags;
  1034. {
  1035.     PyObject *writer, *value, *args, *result;
  1036.     if (f == NULL) {
  1037.         PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
  1038.         return -1;
  1039.     }
  1040.     else if (PyFile_Check(f)) {
  1041.         FILE *fp = PyFile_AsFile(f);
  1042.         if (fp == NULL) {
  1043.             err_closed();
  1044.             return -1;
  1045.         }
  1046.         return PyObject_Print(v, fp, flags);
  1047.     }
  1048.     writer = PyObject_GetAttrString(f, "write");
  1049.     if (writer == NULL)
  1050.         return -1;
  1051.     if (flags & Py_PRINT_RAW)
  1052.         value = PyObject_Str(v);
  1053.     else
  1054.         value = PyObject_Repr(v);
  1055.     if (value == NULL) {
  1056.         Py_DECREF(writer);
  1057.         return -1;
  1058.     }
  1059.     args = Py_BuildValue("(O)", value);
  1060.     if (args == NULL) {
  1061.         Py_DECREF(value);
  1062.         Py_DECREF(writer);
  1063.         return -1;
  1064.     }
  1065.     result = PyEval_CallObject(writer, args);
  1066.     Py_DECREF(args);
  1067.     Py_DECREF(value);
  1068.     Py_DECREF(writer);
  1069.     if (result == NULL)
  1070.         return -1;
  1071.     Py_DECREF(result);
  1072.     return 0;
  1073. }
  1074.  
  1075. int
  1076. PyFile_WriteString(s, f)
  1077.     char *s;
  1078.     PyObject *f;
  1079. {
  1080.     if (f == NULL) {
  1081.         /* Should be caused by a pre-existing error */
  1082.         if(!PyErr_Occurred())
  1083.             PyErr_SetString(PyExc_SystemError,
  1084.                     "null file for PyFile_WriteString");
  1085.         return -1;
  1086.     }
  1087.     else if (PyFile_Check(f)) {
  1088.         FILE *fp = PyFile_AsFile(f);
  1089.         if (fp == NULL) {
  1090.             err_closed();
  1091.             return -1;
  1092.         }
  1093.         fputs(s, fp);
  1094.         return 0;
  1095.     }
  1096.     else if (!PyErr_Occurred()) {
  1097.         PyObject *v = PyString_FromString(s);
  1098.         int err;
  1099.         if (v == NULL)
  1100.             return -1;
  1101.         err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
  1102.         Py_DECREF(v);
  1103.         return err;
  1104.     }
  1105.     else
  1106.         return -1;
  1107. }
  1108.